package ypmits.ik {
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	/**
	 * @author Dave Lenz
	 */
	public class IKBone extends Sprite {
		public var ikboneVO : IKBoneVO;
		private var father : DisplayObject;
		private var d : Number = 50;
		public var nextIKBone : *;

		
		
		public function IKBone( ) {
			addEventListener( Event.ADDED_TO_STAGE, init );
		}

		
		private function init(event : Event) : void {
			removeEventListener( Event.ADDED_TO_STAGE, init );

		}

		
		private function startDragHandler( e : MouseEvent ) : void {
			addEventListener( Event.ENTER_FRAME, move );
		}

		
		private function stopDragHandler( e : MouseEvent ) : void {
			removeEventListener( Event.ENTER_FRAME, move );
		}

		
		private function move( e : Event ) : void {
			if (father == null) {
				x = mouseX;
				y = mouseY;
			} else {
				makeMove( father );
				setAngles( father );
			}
			
			for (var i : int = 0; i < ikboneVO.neighbours.length ; ++i) {
				if (ikboneVO.neighbours[i] != father) ikboneVO.neighbours[i].move( this );
			}
		}

		
		private function setAngles( father : DisplayObject) : void {
			var a : *;
			var b : *;
			var c : *;
			var sangle : Number;
			for (var i : int = 0; i < ikboneVO.fpr.length ; i++) {
				var border : Number = 0;
				var node : Number = ikboneVO.fpr[i];
				if (node[1] == parent) {
					//have to move first neighbour and itself
					a = node[1];
					b = node[0];
					c = this;
					sangle = 2 * Math.PI - node[2] - node[3];
				} else if (node[0] == parent) {
					//have to move second neighbour and itslef
					a = node[0];
					b = node[1];
					c = this;
					sangle = node[2];
				} else {
					//if parent is not a fixed member, have to move just second neighbour
					a = node[0];
					b = node[1];
					c = "";
					sangle = node[2];
				}
				var ax : Number = a.x - this.x;
				var ay : Number = a.y - this.y;
				var aangle : Number = Math.atan2( ay, ax );
				var bx : Number = b.x - this.x;
				var by : Number = b.y - this.y;
				var bangle : Number = Math.atan2( by, bx );
				var maxangle : Number = node[3];
				if (maxangle == 0) {
					//if theres no limiting angle, just places member to its position definied by the angle
					b.x = this.x + Math.cos( aangle + sangle ) * d;
					b.y = this.y + Math.sin( aangle + sangle ) * d;
				} else {
					//must not to go under 0
					if (bangle < aangle) bangle += 2 * Math.PI; 
					//if there is a limiting angle(sangle and sangle+maxangle) checks if present position is 
					//under or over the limit, and sets closest border.
					//if its under the lowest limit
					if (bangle < aangle + sangle) border = sangle;
					//if its over the highest limit
					if (bangle > aangle + sangle + maxangle) border = sangle + maxangle;
					if (border != 0) {
						var cx : Number = b.x - a.x;
						var cy : Number = b.y - a.y;
						var cangle : Number = Math.atan2( cy, cx );
						//calculates the ar and br sided (d and d here), limiting angled triangle described in fig 5
						var px : Number = d - Math.cos( border ) * d;
						var py : Number = Math.sin( border ) * d;
						var mind : Number = Math.sqrt( px * px + py * py );
						var gamma : Number = Math.atan2( py, px );
						var deltha : Number = Math.PI - border - gamma;
						//the third angle of the triangle, at origo
						//and repositioning
						b.x = a.x + Math.cos( cangle ) * mind;
						b.y = a.y + Math.sin( cangle ) * mind;
						var thisang : Number = cangle + deltha;
						c.x = a.x + Math.cos( thisang ) * d;
						c.y = a.y + Math.sin( thisang ) * d;
					}
				}
			}
		}

		
		private function makeMove( parent : DisplayObject ) : void {
			var dx : Number = x - parent.x;
			var dy : Number = y - parent.y;
			var angle : Number = Math.atan2( dy, dx );
			x = parent.x + Math.cos( angle ) * d;
			y = parent.y + Math.sin( angle ) * d;
			rotation = (Math.PI + angle) * 180 / Math.PI;
		};

		
		
		public function enable() : void 
		{
		}
	}
}
